#include "stdafx.h"
#include "HBoxPlacerRule.h"
#include "GameItem.h"
#include "GameRoom.h"
#include "HSceneConfig.h"
#include "HRoomManager.h"
#include "HGlobalManager.h"
#include "HLifeManager.h"
#include "HBoxes.h"
#include "HBombs.h"
#include "UILogic/HBombBoxWnd.h"

namespace OSLib
{
	template<> BombBox::BoxPlacerRuler* Singleton<BombBox::BoxPlacerRuler>::ms_Singleton = NULL;
}


namespace BombBox
{
	bool BOXUTIL::grid( float x, float y, float z, int& ix, int& iy, int& iz )
	{
		int tx = int(x * 0.1f);
		int ty = int(y * 0.1f);
		int tz = int(z * 0.1f);

		if( tx > MAX_BOX_X_HALF || tx < -MAX_BOX_X_HALF ) return false;
		if( ty > MAX_BOX_Y_HALF*2 || ty < 0 ) return false;
		if( tz > MAX_BOX_Z_HALF || tz < -MAX_BOX_Z_HALF ) return false;

		ix = MAX_BOX_X_HALF + tx;
		iy = ty;
		iz = MAX_BOX_Z_HALF + tz;

		return true;
	}

	irr::core::vector3df BOXUTIL::getRenderPos( int x, int y, int z )
	{
		return irr::core::vector3df( 10.0f*(x - MAX_BOX_X_HALF), 10.0f*y, 10.0f*(z - MAX_BOX_Z_HALF) );
	}

	BoxPlacerRuler::BoxPlacerRuler( void )
	{
		clear( NULL );
	}

	BoxPlacerRuler::~BoxPlacerRuler( void )
	{
	}

	bool BoxPlacerRuler::clear( SceneConfig* pConfig )
	{
		m_pConfig = pConfig;
		memset(vBoxs,0,sizeof(vBoxs));
		return true;
	}

	bool BoxPlacerRuler::canPlace( const irr::core::vector3df& vPos, SceneConfig* pConfig )
	{
		if( pConfig == NULL ) return false;
		if( pConfig != m_pConfig ) return false;

		int ix,iy,iz;
		if( !BOXUTIL::grid(vPos.X, vPos.Y, vPos.Z, ix, iy, iz) ) return false;

		return (vBoxs[ix][iy][iz] == NULL);
	}

	bool BoxPlacerRuler::addBox( const irr::core::vector3df& vPos, GameItem* pBox, SceneConfig* pConfig )
	{
		if( pConfig == NULL ) return false;
		if( pConfig != m_pConfig ) return false;
		if( m_pConfig->isPublished() ) return false;

		int ix,iy,iz;
		if( !BOXUTIL::grid(vPos.X, vPos.Y, vPos.Z, ix, iy, iz) ) return false;

		if( vBoxs[ix][iy][iz] != NULL ) return false;
		if( iy > 0 )
		if( vBoxs[ix][iy-1][iz] == NULL || vBoxs[ix][iy-1][iz]->getType() > 200 ) return false;

		vBoxs[ix][iy][iz] = pBox;

		m_pConfig->addData( ix,iy,iz,pBox->getType() );
		return true;
	}

	bool BoxPlacerRuler::addBomb( const irr::core::vector3df& vPos, GameItem* pBomb, SceneConfig* pConfig )
	{
		if( pConfig == NULL ) return false;
		if( pConfig != m_pConfig ) return false;

		int ix,iy,iz;
		if( !BOXUTIL::grid(vPos.X, vPos.Y, vPos.Z, ix, iy, iz) ) return false;

		if( vBoxs[ix][iy][iz] != NULL ) return false;
		if( iy>0 && vBoxs[ix][iy-1][iz] == NULL ) return false;

		// Bomb Logic

		return true;
	}

	void BoxPlacerRuler::remove( GameItem* pItem )
	{
		if( !pItem ) return;

		for( int i=0; i<MAX_BOX_X_HALF*2+1; ++i )
		for( int j=0; j<MAX_BOX_Y_HALF*2+1; ++j )
		for( int k=0; k<MAX_BOX_Z_HALF*2+1; ++k )
		{
			if( vBoxs[i][j][k] == pItem )
			{
				vBoxs[i][j][k] = NULL;
				return;
			}
		}

	}

	void BoxPlacerRuler::loadConfig( SceneConfig* pConfig )
	{
		clear( pConfig );

		// initialize Room
		GameRoom* pRoom = s_pRoomManager->getActiveRoom();
		RoomController* pRoomController = pRoom->getController();
		if( pRoomController == NULL ) return;

		pRoom->setRoomFile( m_pConfig->getMapName() );

		// initialize Box
		const irr::core::array<Slot>& slots = pConfig->getData();
		int nCount = slots.size();
		for( int i=0; i<nCount; ++i )
		{
			const Slot& s = slots[i];

			if( s.nX <0 || s.nX >= MAX_BOX_X_HALF*2+1 ) continue;
			if( s.nY <0 || s.nY >= MAX_BOX_Y_HALF*2+1 ) continue;
			if( s.nZ <0 || s.nZ >= MAX_BOX_Z_HALF*2+1 ) continue;
			if( vBoxs[s.nX][s.nY][s.nZ] != NULL ) continue;

			BoxItem* pBox = s_pBoxesManager->createBox( s.nType );
			if( pBox == NULL ) continue;

			vBoxs[s.nX][s.nY][s.nZ] = pBox;

			pBox->setPosition( BOXUTIL::getRenderPos( s.nX, s.nY, s.nZ ) );
			ItemController* pItemController = pRoomController->addNewItem( pBox );
			pItemController->updateStatus( 100 );
			pBox->setItemController( pItemController );

			pRoom->registerBox( pBox );
		}

		// Load Bomb
		vBombs[0] = pConfig->getBombCnt(401);
		vBombs[1] = pConfig->getBombCnt(402);
		vBombs[2] = pConfig->getBombCnt(403);
		vBombs[3] = pConfig->getBombCnt(404);
		g_BBWnd->setBombCount( vBombs[0], vBombs[1], vBombs[2], vBombs[3] );

		pRoomController->initialize();
	}

	void BoxPlacerRuler::saveConfig( SceneConfig* pConfig )
	{
		if( pConfig == NULL ) return;
		if( pConfig != m_pConfig ) return;

		m_pConfig->clear();

		for( int i=0; i<MAX_BOX_X_HALF*2+1; ++i )
		for( int j=0; j<MAX_BOX_Y_HALF*2+1; ++j )
		for( int k=0; k<MAX_BOX_Z_HALF*2+1; ++k )
		{
			if( vBoxs[i][j][k] != NULL )
			{
				m_pConfig->addData( i,j,k,vBoxs[i][j][k]->getType() );
			}
		}
	}

	void BoxPlacerRuler::doBomb( GameItem* pItem )
	{
		BombItem* pBomb = dynamic_cast<BombItem*>(pItem);
		if( pBomb == NULL ) return;

		irr::core::vector3df vPos = pBomb->getPosition(0);
		//int ix,iy,iz;
		//if( !BOXUTIL::grid(vPos.X, vPos.Y, vPos.Z, ix, iy, iz) ) return;

		GameRoom* pRoom = s_pRoomManager->getActiveRoom();
		RoomController* pRoomController = pRoom->getController();
		if( pRoomController == NULL ) return;

		s_pLifeManager->addDefaultParticle(vPos,2);

		pBomb->doBomb();
		pRoomController->removeItem(pBomb);
	}

	void BoxPlacerRuler::onBoxBomb( int x, int y, int z )
	{
		vBoxs[x][y][z] = NULL;
		// Fall
		for( int i=y+1; i<MAX_BOX_Y_HALF*2+1; ++i )
		{
			if( vBoxs[x][i][z] != NULL )
			{
				BoxItem* pBox = dynamic_cast<BoxItem*>(vBoxs[x][i][z]);
				if( pBox == NULL ) return;

				vBoxs[x][i-1][z] = vBoxs[x][i][z];
				pBox->getItemController()->setPosition( BOXUTIL::getRenderPos( x, i-1, z ) );
				vBoxs[x][i][z] = NULL;
			}
		}
	}

	GameItem* BoxPlacerRuler::getGameItem( int x, int y, int z )
	{
		if( x <0 || x >= MAX_BOX_X_HALF*2+1 ) return NULL;
		if( y <0 || y >= MAX_BOX_Y_HALF*2+1 ) return NULL;
		if( z <0 || z >= MAX_BOX_Z_HALF*2+1 ) return NULL;
		return vBoxs[x][y][z];
	}
}